今天來製作 books API 端點!
首先要先創建一個新的 app,到rest_api中輸入:
python manage.py startapp book
建立完成後記得加入settings.py的INSTALLED_APPS中。books app 預計只會有 serializers, urls, views,而 book model 會加在 core app 中。再來到core/models.py中加入:
# 其他導入
from django.conf import settings
# ...
class Book(models.Model):
    """Book object."""
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    price = models.IntegerField()
    def __str__(self):
        return self.title
這邊在 book model 底下創建四個欄位: user, title, description, price。ForeignKey可使兩欄位產生連結,第一個參數為了避免 hard code,所以使用settings.AUTH_USER_MODEL,而on_delete=models.CASCADE表示 user 被刪除時,其創建的 book object 也會一併被刪除。最底下的__str__函式會將 title 顯示在管理員頁面中。完成後儲存並執行 migration 創建此資料表。最後記得在admin.py中註冊此 model。
此處 Book 繼承的是
models.Model,與 User model 不同。
接著到 book app 中新增serializers.py檔案並加入:
from rest_framework import serializers
from core.models import Book
class BookSerializer(serializers.ModelSerializer):
    """Serializer for books."""
    class Meta:
        model = Book
        fields = ['id', 'title', 'price']
        read_only_fields = ['id']
這邊的 serializer 同樣繼承ModelSerializer並指定 Book 為進行序列化的 model,此外指定 id 為僅供讀取的欄位。完成後到 book/views.py 中新增:
"""
Views for the book APIs.
"""
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from core.models import Book
from book import serializers
class BookViewSet(viewsets.ModelViewSet):
    """View for manage book APIs."""
    serializer_class = serializers.BookSerializer
    queryset = Book.objects.all()
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    def get_queryset(self):
        """Retrieve books for authenticated user."""
        return self.queryset.filter(user=self.request.user).order_by('-id')
此處繼承ModelViewSet並指定剛剛創建的BookSerializer為serializer_class,預設的查詢資料為所有 book objects。此端點需要授權才能進行操作,所以記得加上之前的授權方法。下方的功能是只回傳該使用者上傳的物件。完成後創建urls.py並加入:
"""
URL mappings for the book app.
"""
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from book import views
router = DefaultRouter()
router.register('books', views.BookViewSet)
app_name = 'book'
urlpatterns = [
    path('', include(router.urls)),
]
這邊使用router = DefaultRouter()來自動創建 CRUD 所需的 urls,創建完成後註冊router.register('books', views.BookViewSet)。最後加進 urlpatterns 中。完成後進入 rest_api/urls.py 中加入 book 中的 urls:
urlpatterns = [
    # ...
    path('api/book/', include('book.urls')),
]
完成後,執行伺服器的時候就可以看到所有 book API 的端點顯示在 Swagger 頁面上,像這樣:
功能的部分尚未實作完畢,因此照目前裝況去測試某些端點時會發生錯誤。明天就來把功能都做完,掰掰。